home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 6 / CU Amiga Magazine's Super CD-ROM 06 (1996)(EMAP Images)(GB)(Track 1 of 4)[!][issue 1997-01].iso / cucd / prog / gnu-c / fd2inline-1.1 / src / fd2inline.c < prev    next >
C/C++ Source or Header  |  1996-10-24  |  46KB  |  2,030 lines

  1. /******************************************************************************
  2.  *
  3.  * fd2inline
  4.  *
  5.  * Should be able to parse CBM fd files and generate vanilla inline calls
  6.  * for gcc. Works as a filter. This is a 0.9 evaluation version.
  7.  * Don't expect miracles (yet...).
  8.  *
  9.  * by Wolfgang Baron, all rights reserved.
  10.  *
  11.  * improved, updated, simply made workable by Rainer F. Trunz 1/95
  12.  *
  13.  * Completely reworked Version, cleaned up and removed a whole lot of bugs
  14.  * found by Kamil Iskra.
  15.  *
  16.  * Expect miracles now (hopefully...). Ok, I am just kidding :)
  17.  *
  18.  * Version 0.99a by Rainer F. Trunz 6/95
  19.  *
  20.  * Version 0.99b and later by Kamil Iskra.
  21.  *
  22.  ******************************************************************************/
  23.  
  24. #include <ctype.h>
  25. #include <stddef.h>
  26. #include <stdio.h>
  27. #include <stdlib.h>
  28. #include <string.h>
  29.  
  30. /******************************************************************************
  31.  * The program has a few sort of class definitions, which are the result of
  32.  * object oriented thinking, to be imlemented in plain C. I just haven't
  33.  * had the time to learn C++ or install the compiler. The design does however
  34.  * improve robustness, which allows the source to be used over and over again.
  35.  * if you use this code, please leave a little origin note.
  36.  ******************************************************************************/
  37.  
  38. const static char version_str[]="$VER: fd2inline " VERSION " (24.10.96)";
  39.  
  40. /******************************************************************************
  41.  * These are general definitions including types for defining registers etc.
  42.  ******************************************************************************/
  43.  
  44. #ifdef DEBUG
  45. #define DBP(a) a
  46. #else /* !DEBUG */
  47. #define DBP(a)
  48. #endif /* !DEBUG */
  49.  
  50. #if (defined(__GNUC__) || defined(__SASC)) && 0
  51. #define INLINE __inline /* Gives 20% *larger* executable with GCC?! */
  52. #else
  53. #define INLINE
  54. #endif
  55.  
  56. #define REGS 16  /* d0=0,...,a7=15 */
  57. #define FDS 1000
  58.  
  59. typedef enum
  60. {
  61.     d0, d1, d2, d3, d4, d5, d6, d7, a0, a1, a2, a3, a4, a5, a6, a7, illegal
  62. } regs;
  63.  
  64. typedef unsigned char uchar, shortcard;
  65. typedef unsigned long ulong;
  66.  
  67. typedef enum { false, nodef, real_error } Error;
  68.  
  69. enum {NEW, OLD, STUBS, PROTO} output_mode=NEW;
  70.  
  71. char BaseName[32], BaseNamU[32],  BaseNamL[32];
  72.  
  73. const static char *LibExcTable[]=
  74. {
  75.     "BattClockBase",            "Node",
  76.     "BattMemBase",                "Node",
  77.     "ConsoleDevice",            "Device",
  78.     "DiskBase",                    "DiskResource",
  79.     "DOSBase",                    "DosLibrary",
  80.     "SysBase",                    "ExecBase",
  81.     "ExpansionBase",            "ExpansionBase",
  82.     "GfxBase",                    "GfxBase",
  83.     "InputBase",                "Device",
  84.     "IntuitionBase",            "IntuitionBase",
  85.     "LocaleBase",                "LocaleBase",
  86.     "MathIeeeDoubBasBase",    "MathIEEEBase",
  87.     "MathIeeeDoubTransBase","MathIEEEBase",
  88.     "MathIeeeSingBasBase",    "MathIEEEBase",
  89.     "MathIeeeSingTransBase","MathIEEEBase",
  90.     "MiscBase",                    "Node",
  91.     "PotgoBase",                "Node",
  92.     "RamdriveDevice",            "Device",
  93.     "RealTimeBase",            "RealTimeBase",
  94.     "RexxSysBase",                "RxsLib",
  95.     "TimerBase",                "Device",
  96.     "UtilityBase",                "UtilityBase"
  97. };
  98. const char *StdLib; /* global lib-name ptr */
  99.  
  100. /*******************************************
  101.  * just some support functions, no checking
  102.  *******************************************/
  103.  
  104. char*
  105. NewString(char** new, const char* old)
  106. {
  107.     const char *high;
  108.     ulong len;
  109.  
  110.     while (*old && (*old==' ' || *old=='\t'))
  111.         old++;
  112.     len=strlen(old);
  113.     for (high=old+len-1; high>=old && (*high==' ' || *high=='\t'); high--);
  114.     high++;
  115.     len=high-old;
  116.     *new=malloc(1+len);
  117.     if (*new)
  118.     {
  119.         strncpy(*new, old, len);
  120.         (*new)[len]='\0';
  121.     }
  122.     else
  123.         fprintf(stderr, "no mem for string\n");
  124.     return *new;
  125. }
  126.  
  127. static INLINE void
  128. illparams(const char* funcname)
  129. {
  130.     fprintf(stderr, "%s: illegal Parameters\n", funcname);
  131. }
  132.  
  133. static INLINE const char*
  134. RegStr(regs reg)
  135. {
  136.     const static char *myregs[]=
  137.     {
  138.         "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
  139.         "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "illegal"
  140.     };
  141.  
  142.     if (reg>illegal)
  143.         reg=illegal;
  144.     if (reg<d0)
  145.         reg=d0;
  146.     return myregs[reg];
  147. }
  148.  
  149. /******************************************************************************
  150.  *    StrNRBrk
  151.  *
  152.  * searches string in from position at downwards, as long as in does not
  153.  * contain any character in not.
  154.  *
  155.  ******************************************************************************/
  156.  
  157. const char*
  158. StrNRBrk(const char* in, const char* not, const char* at)
  159. {
  160.     const char *chcheck;
  161.     Error ready;
  162.  
  163.     chcheck=""; /* if at<in, the result will be NULL */
  164.     for (ready=false; ready==false && at>=in;)
  165.     {
  166.         for (chcheck=not; *chcheck && *chcheck != *at; chcheck++);
  167.         if (*chcheck)
  168.             ready=real_error;
  169.         else
  170.             at--;
  171.     }
  172.     DBP(fprintf(stderr, "{%c}", *chcheck));
  173.     return *chcheck ? at : NULL;
  174. }
  175.  
  176. /*
  177.   Our own "strupr", since it is a non-standard function.
  178. */
  179. void
  180. StrUpr(char* str)
  181. {
  182.     while (*str)
  183.     {
  184.         *str=toupper(*str);
  185.         str++;
  186.     }
  187. }
  188.  
  189. /******************************************************************************
  190.  *    CLASS fdFile
  191.  *
  192.  * stores a file with a temporary buffer (static length, sorry), a line number,
  193.  * an offset (used for library offsets and an error field.
  194.  * When there's no error, line will contain line #lineno and offset will be
  195.  * the last offset set by the interpretation of the last line. If there's been
  196.  * no ##bias line, this field assumes a bias of 30, which is the standard bias.
  197.  * It is assumed offsets are always negative.
  198.  ******************************************************************************/
  199.  
  200. #define fF_BUFSIZE 1024
  201.  
  202. /* all you need to know about an fdFile you parse */
  203.  
  204. typedef struct
  205. {
  206.     FILE*    file;                    /* the file we're reading from        */
  207.     char    line[fF_BUFSIZE];    /* the current line                        */
  208.     ulong    lineno;                /* current line number                    */
  209.     long    offset;                /* current fd offset (-bias)            */
  210.     Error    error;                /* is everything o.k.                    */
  211.     char    private;                /* are we in ##public or ##private    */
  212. } fdFile;
  213.  
  214. fdFile*
  215. fF_ctor            (const char* fname);
  216. static void
  217. fF_dtor            (fdFile* obj);
  218. static void
  219. fF_SetError        (fdFile* obj, Error error);
  220. static void
  221. fF_SetOffset    (fdFile* obj, long at);
  222. Error
  223. fF_readln        (fdFile* obj);
  224. static Error
  225. fF_GetError        (const fdFile* obj);
  226. static long
  227. fF_GetOffset    (const fdFile* obj);
  228. char*
  229. fF_FuncName        (fdFile* obj); /* return name or null */
  230. static void
  231. fF_SetPrivate    (fdFile* obj, char priv);
  232. static char
  233. fF_GetPrivate    (const fdFile* obj);
  234.  
  235. static INLINE void
  236. fF_dtor(fdFile* obj)
  237. {
  238.   fclose(obj->file);
  239.   free(obj);
  240. }
  241.  
  242. static INLINE void
  243. fF_SetError(fdFile* obj, Error error)
  244. {
  245.     if (obj)
  246.         obj->error=error;
  247.     else
  248.         illparams("fF_SetError");
  249. }
  250.  
  251. static INLINE void
  252. fF_SetOffset(fdFile* obj, long at)
  253. {
  254.     if (obj)
  255.         obj->offset= at;
  256.     else
  257.         illparams("fFSetOffset");
  258. }
  259.  
  260. static INLINE void
  261. fF_SetPrivate(fdFile* obj, char priv)
  262. {
  263.   if (obj)
  264.     obj->private=priv;
  265.   else
  266.     illparams("fF_SetPrivate");
  267. }
  268.  
  269. fdFile*
  270. fF_ctor(const char* fname)
  271. {
  272.     fdFile *result;
  273.  
  274.     if (fname)
  275.     {
  276.         result=malloc(sizeof(fdFile));
  277.         if (result)
  278.         {
  279.             result->file=fopen(fname, "r");
  280.             if (result->file)
  281.             {
  282.                 result->lineno=0;
  283.                 fF_SetOffset(result, -30);
  284.                 fF_SetError(result, false);
  285.                 fF_SetPrivate(result, 0);
  286.                 result->line[0]='\0';
  287.             }
  288.             else
  289.             {
  290.                 free(result);
  291.                 result=NULL;
  292.             }
  293.         }
  294.     }
  295.     else
  296.     {
  297.         result=NULL;
  298.         illparams("fF_ctor");
  299.     }
  300.     return result;
  301. }
  302.  
  303. Error
  304. fF_readln(fdFile* obj)
  305. {
  306.     char *low, *bpoint;
  307.     long glen,    /* the length we read until now */
  308.     len;            /* the length of the last segment */
  309.  
  310.     if (obj)
  311.     {
  312.         low=obj->line;
  313.         glen=0;
  314.  
  315.         for (;;)
  316.         {
  317.             obj->lineno++;
  318.             if (!fgets(low, fF_BUFSIZE-1-glen, obj->file))
  319.             {
  320.                 fF_SetError(obj, real_error);
  321.                 obj->line[0]='\0';
  322.                 return real_error;
  323.             }
  324.             if (low==strpbrk(low, "*#/"))
  325.             {
  326.                 DBP(fprintf(stderr, "in# %s\n", obj->line));
  327.                 return false;
  328.             }
  329.             len=strlen(low);
  330.             bpoint=low+len-1;
  331.             while (len && isspace(*bpoint))
  332.             {
  333.                 bpoint--;
  334.                 len--;
  335.             }
  336.             if (*bpoint==';' || *bpoint==')')
  337.             {
  338.                 DBP(fprintf(stderr, "\nin: %s\n", obj->line));
  339.                 return false;
  340.             }
  341.             glen+=len;
  342.             low+=len;
  343.             if (glen>=fF_BUFSIZE-10) /* somewhat pessimistic? */
  344.             {
  345.                 fF_SetError(obj, real_error);
  346.                 fprintf(stderr, "line %lu too long.\n", obj->lineno);
  347.                 return real_error;
  348.             }
  349.             DBP(fprintf(stderr, "+"));
  350.         }
  351.     }
  352.     illparams("fF_readln");
  353.     return real_error;
  354. }
  355.  
  356. static INLINE Error
  357. fF_GetError(const fdFile* obj)
  358. {
  359.     if (obj)
  360.         return obj->error;
  361.     illparams("fF_GetError");
  362.     return real_error;
  363. }
  364.  
  365. static INLINE long
  366. fF_GetOffset(const fdFile* obj)
  367. {
  368.     if (obj)
  369.         return obj->offset;
  370.     illparams("fF_GetOffset");
  371.     return -1;
  372. }
  373.  
  374. /******************************************************************************
  375.  * fF_FuncName
  376.  *
  377.  * checks if it can find a function-name and return it's address, or NULL
  378.  * if the current line does not seem to contain one. The return value will
  379.  * be a pointer into a malloced buffer, thus the caller will have to free().
  380.  ******************************************************************************/
  381.  
  382. char*
  383. fF_FuncName(fdFile* obj)
  384. {
  385.     const char *lower;
  386.     const char *upper;
  387.     char *buf;
  388.     long obraces;    /* count of open braces */
  389.     Error ready;    /* ready with searching */
  390.  
  391.     if (!obj || fF_GetError(obj)==real_error)
  392.     {
  393.         illparams("fF_FuncName");
  394.         return NULL;
  395.     }
  396.  
  397.     lower=obj->line;
  398.     while (*lower && (*lower==' ' || *lower=='\t'))
  399.         lower++;
  400.  
  401.     if (!*lower || (!isalpha(*lower) && *lower!='_'))
  402.     {
  403.         fF_SetError(obj, nodef);
  404.         return NULL;
  405.     }
  406.  
  407.     while (*lower)
  408.     {
  409.         if (!isalnum(*lower) && !isspace(*lower) && *lower!='*' && *lower!=','
  410.         && *lower!='.' && *lower!=';' && *lower!='(' && *lower!=')' &&
  411.         *lower!='[' && *lower!=']' && *lower!='_' && *lower!='\\')
  412.         {
  413.             fF_SetError(obj, nodef);
  414.             return NULL;
  415.         }
  416.         lower++;
  417.     }
  418.  
  419.     lower=NULL;
  420.     buf=NULL;
  421.  
  422.     if (obj && fF_GetError(obj)==false)
  423.     {
  424.         if ((upper=strrchr(obj->line, ')'))!=0)
  425.         {
  426.             DBP(fprintf(stderr, "end:%s:", upper));
  427.  
  428.             for (obraces=1, ready=false; ready==false; upper=lower)
  429.             {
  430.                 lower=StrNRBrk(obj->line, "()", --upper);
  431.                 if (lower)
  432.                 {
  433.                     switch (*lower)
  434.                     {
  435.                         case ')':
  436.                             obraces++;
  437.                             DBP(fprintf(stderr, " )%ld%s", obraces, lower));
  438.                             break;
  439.                         case '(':
  440.                             obraces--;
  441.                             DBP(fprintf(stderr, " (%ld%s", obraces, lower));
  442.                             if (!obraces)
  443.                                 ready=nodef;
  444.                             break;
  445.                         default:
  446.                             fprintf(stderr, "faulty StrNRBrk\n");
  447.                     }
  448.                 }
  449.                 else
  450.                 {
  451.                     fprintf(stderr, "'(' or ')' expected in line %lu.\n",
  452.                         obj->lineno);
  453.                     ready=real_error;
  454.                 }
  455.             }
  456.             if (ready==nodef) /* we found the matching '(' */
  457.             {
  458.                 long newlen;
  459.                 const char* name;
  460.  
  461.                 upper--;
  462.  
  463.                 while (upper>=obj->line && (*upper==' ' || *upper=='\t'))
  464.                     upper--;
  465.  
  466.                 lower=StrNRBrk(obj->line, " \t*)", upper);
  467.  
  468.                 if (!lower)
  469.                     lower=obj->line;
  470.                 else
  471.                     lower++;
  472.  
  473.                 for (name=lower; name<=upper; name++)
  474.                     if (!isalnum(*name) && *name!='_')
  475.                     {
  476.                         fF_SetError(obj, nodef);
  477.                         return NULL;
  478.                     }
  479.  
  480.                 newlen=upper-lower+1;
  481.                 buf=malloc(newlen+1);
  482.  
  483.                 if (buf)
  484.                 {
  485.                     strncpy(buf, lower, newlen);
  486.                     buf[newlen]='\0';
  487.                 }
  488.                 else
  489.                     fprintf(stderr, "no mem for fF_FuncName");
  490.             }
  491.         }
  492.     }
  493.     else
  494.         illparams("fF_FuncName");
  495.     return buf;
  496. }
  497.  
  498. static INLINE char
  499. fF_GetPrivate(const fdFile* obj)
  500. {
  501.     if (obj)
  502.         return obj->private;
  503.     illparams("fF_GetPrivate");
  504.     return 0;
  505. }
  506.  
  507. /*********************
  508.  *    CLASS fdDef    *
  509.  *********************/
  510.  
  511. typedef struct
  512. {
  513.     char*    name;
  514.     char*    type;
  515.     long    offset;
  516.     regs    reg[REGS];
  517.     char*    param[REGS];
  518.     char*    proto[REGS];
  519.     regs    funcpar; /* number of argument that has type "pointer to function" */
  520. } fdDef;
  521.  
  522. fdDef*
  523. fD_ctor                (void);
  524. void
  525. fD_dtor                (fdDef* obj);
  526. static void
  527. fD_NewName            (fdDef* obj, const char* newname);
  528. void
  529. fD_NewParam            (fdDef* obj, shortcard at, const char* newstr);
  530. void
  531. fD_NewProto            (fdDef* obj, shortcard at, char* newstr);
  532. static void
  533. fD_NewReg            (fdDef* obj, shortcard at, regs reg);
  534. static void
  535. fD_NewType            (fdDef* obj, const char* newstr);
  536. static void
  537. fD_SetOffset        (fdDef* obj, long off);
  538. Error
  539. fD_parsefd            (fdDef* obj, fdFile* infile);
  540. Error
  541. fD_parsepr            (fdDef* obj, fdFile* infile);
  542. static const char*
  543. fD_GetName            (const fdDef* obj);
  544. static long
  545. fD_GetOffset        (const fdDef* obj);
  546. static const char*
  547. fD_GetParam            (const fdDef* obj, shortcard at);
  548. static regs
  549. fD_GetReg            (const fdDef* obj, shortcard at);
  550. static const char*
  551. fD_GetRegStr        (const fdDef* obj, shortcard at);
  552. static const char*
  553. fD_GetType            (const fdDef* obj);
  554. static shortcard
  555. fD_ParamNum            (const fdDef* obj);
  556. static shortcard
  557. fD_ProtoNum            (const fdDef* obj);
  558. static shortcard
  559. fD_RegNum            (const fdDef* obj);
  560. int
  561. fD_cmpName            (const void* big, const void* small);
  562. void
  563. fD_write                (FILE* outfile, const fdDef* obj);
  564. static shortcard
  565. fD_GetFuncParNum    (const fdDef* obj);
  566. static void
  567. fD_SetFuncParNum    (fdDef* obj, shortcard at);
  568.  
  569. fdDef **arrdefs;
  570. long fds;
  571.  
  572. char *fD_nostring="";
  573.  
  574. fdDef*
  575. fD_ctor(void)
  576. {
  577.     fdDef *result;
  578.     regs count;
  579.  
  580.     result=malloc(sizeof(fdDef));
  581.  
  582.     if (result)
  583.     {
  584.         result->name=fD_nostring;
  585.         result->type=fD_nostring;
  586.         result->funcpar=illegal;
  587.  
  588.         for (count=d0; count<illegal; count++ )
  589.         {
  590.             result->reg[count]=illegal;
  591.             result->param[count]=fD_nostring; /* if (!strlen) dont't free() */
  592.             result->proto[count]=fD_nostring;
  593.         }
  594.     }
  595.     return result;
  596. }
  597.  
  598. /* free all resources and make the object as illegal as possible */
  599.  
  600. void
  601. fD_dtor(fdDef* obj)
  602. {
  603.     regs count;
  604.  
  605.     if (obj)
  606.     {
  607.         if (!obj->name)
  608.             fprintf(stderr, "fD_dtor: null name");
  609.         else
  610.             if (obj->name!=fD_nostring)
  611.                 free(obj->name);
  612.  
  613.         if (!obj->type)
  614.             fprintf(stderr, "fD_dtor: null type");
  615.         else
  616.             if (obj->type!=fD_nostring)
  617.                 free(obj->type);
  618.  
  619.         obj->name=obj->type=NULL;
  620.  
  621.         for (count=d0; count<illegal; count++)
  622.         {
  623.             obj->reg[count]=illegal;
  624.  
  625.             if (!obj->param[count])
  626.                 fprintf(stderr, "fD_dtor: null param");
  627.             else
  628.                 if (obj->param[count]!=fD_nostring)
  629.                     free(obj->param[count]);
  630.  
  631.             if (!obj->proto[count])
  632.                 fprintf(stderr, "fD_dtor: null proto");
  633.             else
  634.                 if (obj->proto[count]!=fD_nostring)
  635.                     free(obj->proto[count]);
  636.  
  637.             obj->param[count]=obj->proto[count]=NULL;
  638.         }
  639.  
  640.         free(obj);
  641.     }
  642.     else
  643.         fprintf(stderr, "fd_dtor(NULL)\n");
  644. }
  645.  
  646. static INLINE void
  647. fD_NewName(fdDef* obj, const char* newname)
  648. {
  649.     if (obj && newname)
  650.     {
  651.         if (obj->name && obj->name!=fD_nostring)
  652.             free(obj->name);
  653.         if (!NewString(&obj->name, newname))
  654.             obj->name=fD_nostring;
  655.     }
  656.     else
  657.         illparams("fD_NewName");
  658. }
  659.  
  660. void
  661. fD_NewParam(fdDef* obj, shortcard at, const char* newstr)
  662. {
  663.     char *pa;
  664.  
  665.     if (newstr && obj && at<illegal)
  666.     {
  667.         pa=obj->param[at];
  668.  
  669.         if (pa && pa!=fD_nostring)
  670.             free(pa);
  671.  
  672.         while (*newstr==' ' || *newstr=='\t')
  673.             newstr++;
  674.  
  675.         if (NewString(&pa, newstr))
  676.             obj->param[at]=pa;
  677.         else
  678.             obj->param[at]=fD_nostring;
  679.     }
  680.     else
  681.         illparams("fD_NewParam");
  682. }
  683.  
  684. /* get first free *reg or illegal */
  685.  
  686. static INLINE shortcard
  687. fD_RegNum(const fdDef* obj)
  688. {
  689.     shortcard count;
  690.  
  691.     if (obj)
  692.     {
  693.         for (count=d0; count<illegal && obj->reg[count]!=illegal; count++);
  694.         return count;
  695.     }
  696.     else
  697.     {
  698.         illparams("fD_RegNum");
  699.         return illegal;
  700.     }
  701. }
  702.  
  703. static INLINE void
  704. fD_NewReg(fdDef* obj, shortcard at, regs reg)
  705. {
  706.     if (obj && at<illegal && reg>=d0 && reg<=illegal)
  707.         obj->reg[at]=reg;
  708.     else
  709.         illparams("fD_NewReg");
  710. }
  711.  
  712. static INLINE regs
  713. fD_GetReg(const fdDef* obj, shortcard at)
  714. {
  715.     if (obj && at<illegal)
  716.         return obj->reg[at];
  717.     else
  718.     {
  719.         illparams("fD_GetReg");
  720.         return illegal;
  721.     }
  722. }
  723.  
  724. static INLINE shortcard
  725. fD_GetFuncParNum(const fdDef* obj)
  726. {
  727.     if (obj)
  728.         return (shortcard)obj->funcpar;
  729.     else
  730.     {
  731.         illparams("fD_GetFuncParNum");
  732.         return illegal;
  733.     }
  734. }
  735.  
  736. static INLINE void
  737. fD_SetFuncParNum(fdDef* obj, shortcard at)
  738. {
  739.     if (obj && at<illegal)
  740.         obj->funcpar=at;
  741.     else
  742.         illparams("fD_SetFuncParNum");
  743. }
  744.  
  745. void
  746. fD_NewProto(fdDef* obj, shortcard at, char* newstr)
  747. {
  748.     char *pr;
  749.  
  750.     if (newstr && obj && at<illegal)
  751.     {
  752.         char *t, arr[200]; /* I hope 200 will be enough... */
  753.         int numwords=1;
  754.         pr=obj->proto[at];
  755.  
  756.         if (pr && pr!=fD_nostring)
  757.             free(pr);
  758.  
  759.         while (*newstr==' ' || *newstr=='\t')
  760.             newstr++; /* Skip leading spaces */
  761.  
  762.         t=arr;
  763.         while ((*t++=*newstr)!=0)
  764.         {
  765.             /* Copy the rest, counting number of words */
  766.             if ((*newstr==' ' || *newstr=='\t') && newstr[1] && newstr[1]!=' ' &&
  767.             newstr[1]!='\t')
  768.                 numwords++;
  769.             newstr++;
  770.         }
  771.  
  772.         t=arr+strlen(arr)-1;
  773.         while (*t==' ' || *t=='\t')
  774.             t--;
  775.         t[1]='\0'; /* Get rid of tailing spaces */
  776.         if (at!=fD_GetFuncParNum(obj))
  777.         {
  778.             if (numwords>1) /* One word - must be type */
  779.                 if (*t!='*')
  780.                 {
  781.                     /* '*' on the end - no parameter name used */
  782.                     while (*t!=' ' && *t!='\t' && *t!='*')
  783.                         t--;
  784.                     t++;
  785.                     if (strcmp(t, "char") && strcmp(t, "short") && strcmp(t, "int")
  786.                     && strcmp(t, "long"))
  787.                     {
  788.                         /* Not one of applicable keywords - must be parameter name.
  789.                             Get rid of it. */
  790.                         t--;
  791.                         while (*t==' ' || *t=='\t')
  792.                             t--;
  793.                         t[1]='\0';
  794.                     }
  795.                 }
  796.         }
  797.         else
  798.         {
  799.             /* Parameter of type "pointer to function". */
  800.             char *end;
  801.             t=strchr(arr, '(');
  802.             while (*t++!='*');
  803.             end=strchr(t, ')');
  804.             memmove(t+2, end, strlen(end)+1);
  805.             *t='%';
  806.             t[1]='s';
  807.         }
  808.  
  809.         if (NewString(&pr, arr))
  810.         {
  811.             obj->proto[at]=pr;
  812.             while (*pr==' ' || *pr=='\t')
  813.                 pr++;
  814.             if (!stricmp(pr, "double"))
  815.             {
  816.                 /* "double" needs two data registers */
  817.                 int count, regs=fD_RegNum(obj);
  818.                 for (count=at+1; count<regs; count++)
  819.                     fD_NewReg(obj, count, fD_GetReg(obj, count+1));
  820.             }
  821.         }
  822.         else
  823.             obj->proto[at]=fD_nostring;
  824.     }
  825.     else
  826.         illparams("fD_NewProto");
  827. }
  828.  
  829. static INLINE void
  830. fD_NewType(fdDef* obj, const char* newtype)
  831. {
  832.     if (obj && newtype)
  833.     {
  834.         if (obj->type && obj->type!=fD_nostring)
  835.             free(obj->type);
  836.         if (!NewString(&obj->type, newtype))
  837.             obj->type=fD_nostring;
  838.     }
  839.     else
  840.         illparams("fD_NewType");
  841. }
  842.  
  843. static INLINE void
  844. fD_SetOffset(fdDef* obj, long off)
  845. {
  846.     if (obj)
  847.         obj->offset=off;
  848.     else
  849.         illparams("fD_SetOffset");
  850. }
  851.  
  852. static INLINE const char*
  853. fD_GetName(const fdDef* obj)
  854. {
  855.     if (obj && obj->name)
  856.         return obj->name;
  857.     else
  858.     {
  859.         illparams("fD_GetName");
  860.         return fD_nostring;
  861.     }
  862. }
  863.  
  864. static INLINE long
  865. fD_GetOffset(const fdDef* obj)
  866. {
  867.     if (obj)
  868.         return obj->offset;
  869.     else
  870.     {
  871.         illparams("fD_GetOffset");
  872.         return 0;
  873.     }
  874. }
  875.  
  876. static INLINE const char*
  877. fD_GetProto(const fdDef* obj, shortcard at)
  878. {
  879.     if (obj && at<illegal && obj->proto[at])
  880.         return obj->proto[at];
  881.     else
  882.     {
  883.         illparams("fD_GetProto");
  884.         return fD_nostring;
  885.     }
  886. }
  887.  
  888. static INLINE const char*
  889. fD_GetParam(const fdDef* obj, shortcard at)
  890. {
  891.     if (obj && at<illegal && obj->param[at])
  892.         return obj->param[at];
  893.     else
  894.     {
  895.         illparams("fD_GetParam");
  896.         return fD_nostring;
  897.     }
  898. }
  899.  
  900. static INLINE const char*
  901. fD_GetRegStr(const fdDef* obj, shortcard at)
  902. {
  903.     if (obj && at<illegal)
  904.         return RegStr(obj->reg[at]);
  905.     else
  906.     {
  907.         illparams("fD_GetReg");
  908.         return RegStr(illegal);
  909.     }
  910. }
  911.  
  912. static INLINE const char*
  913. fD_GetType(const fdDef* obj)
  914. {
  915.     if (obj && obj->type)
  916.         return obj->type;
  917.     else
  918.     {
  919.         illparams("fD_GetType");
  920.         return fD_nostring;
  921.     }
  922. }
  923.  
  924. /* get first free param or illegal */
  925.  
  926. static INLINE shortcard
  927. fD_ParamNum(const fdDef* obj)
  928. {
  929.     shortcard count;
  930.  
  931.     if (obj)
  932.     {
  933.         for (count=d0; count<illegal && obj->param[count]!=fD_nostring;
  934.         count++);
  935.         return count;
  936.     }
  937.     else
  938.     {
  939.         illparams("fD_ParamNum");
  940.         return illegal;
  941.     }
  942. }
  943.  
  944. static INLINE shortcard
  945. fD_ProtoNum(const fdDef* obj)
  946. {
  947.     shortcard count;
  948.  
  949.     if (obj)
  950.     {
  951.         for (count=d0; count<illegal && obj->proto[count]!=fD_nostring;
  952.         count++);
  953.         return count;
  954.     }
  955.     else
  956.     {
  957.         illparams("fD_ProtoNum");
  958.         return illegal;
  959.     }
  960. }
  961.  
  962. /******************************************************************************
  963.  *    fD_parsefd
  964.  *
  965.  *  parse the current line. Needs to copy input, in order to insert \0's
  966.  *  RETURN
  967.  *    fF_GetError(infile):
  968.  *    false = read a definition.
  969.  *    nodef = not a definition on line (so try again)
  970.  *    error = real error
  971.  ******************************************************************************/
  972.  
  973. Error
  974. fD_parsefd(fdDef* obj, fdFile* infile)
  975. {
  976.     enum parse_info { name, params, regs, ready } parsing;
  977.     char *buf, *bpoint, *bnext;
  978.     ulong index;
  979.  
  980.     if (obj && infile && fF_GetError(infile)==false)
  981.     {
  982.         parsing=name;
  983.  
  984.         if (!NewString(&buf, infile->line))
  985.         {
  986.             fprintf(stderr, "no mem for line %lu\n", infile->lineno);
  987.             fF_SetError(infile, real_error);
  988.         }
  989.         bpoint=buf; /* so -Wall keeps quiet */
  990.  
  991.         /* try to parse the line until there's an error or we are done */
  992.  
  993.         while (parsing!=ready && fF_GetError(infile)==false)
  994.         {
  995.             switch (parsing)
  996.             {
  997.                 case name:
  998.                     switch (buf[0])
  999.                     {
  1000.                         case '#':
  1001.                             if (strncmp("##base", buf, 6)==0)
  1002.                             {
  1003.                                 bnext=buf+6;
  1004.                                 while (*bnext==' ' || *bnext=='\t' || *bnext=='_')
  1005.                                     bnext++;
  1006.                                 strcpy(BaseName, bnext);
  1007.                                 BaseName[strlen(BaseName)-1]='\0';
  1008.                             }
  1009.                             else
  1010.                                 if (strncmp("##bias", buf, 6)==0)
  1011.                                 {
  1012.                                     if (!sscanf(buf+6, "%ld", &infile->offset))
  1013.                                     {
  1014.                                         fprintf(stderr, "illegal ##bias in line %lu: %s\n",
  1015.                                             infile->lineno, infile->line);
  1016.                                         fF_SetError(infile, real_error);
  1017.                                         break; /* avoid nodef */
  1018.                                     }
  1019.                                     else
  1020.                                     {
  1021.                                         if (fF_GetOffset(infile)>0)
  1022.                                             fF_SetOffset(infile, -fF_GetOffset(infile));
  1023.                                         DBP(fprintf(stderr, "set offset to %ld\n",
  1024.                                             fFGetOffset(infile)));
  1025.                                     }
  1026.                                 }
  1027.                                 else
  1028.                                 {
  1029.                                     if (strncmp("##private", buf, 9)==0)
  1030.                                         fF_SetPrivate(infile, 1);
  1031.                                     else
  1032.                                         if (strncmp("##public", buf, 8)==0)
  1033.                                             fF_SetPrivate(infile, 0);
  1034.                                 }
  1035.                             /* drop through for error comment */
  1036.  
  1037.                         case '*':
  1038.                             /* try again somewhere else */
  1039.                             fF_SetError(infile, nodef);
  1040.                                 break;
  1041.  
  1042.                         default:
  1043.                             /* assume a regular line here */
  1044.                             if (fF_GetPrivate(infile))
  1045.                             {
  1046.                                 /* don't store names of privates */
  1047.                                 fF_SetError(infile, nodef);
  1048.                                 fF_SetOffset(infile, fF_GetOffset(infile)-6);
  1049.                                 break;
  1050.                             }
  1051.                             parsing=name; /* switch (parsing) */
  1052.                             for (index=0; buf[index] && buf[index]!='('; index++);
  1053.  
  1054.                             if (!buf[index])
  1055.                             {
  1056.                                 /* oops, no fd ? */
  1057.                                 fprintf(stderr, "not an fd, line %lu: %s\n",
  1058.                                     infile->lineno, buf /* infile->line */);
  1059.                                 fF_SetError(infile, nodef);
  1060.                             } /* maybe next time */
  1061.                             else
  1062.                             {
  1063.                                 buf[index]=0;
  1064.  
  1065.                                 fD_NewName(obj, buf);
  1066.                                 fD_SetOffset(obj, fF_GetOffset(infile));
  1067.  
  1068.                                 bpoint=buf+index+1;
  1069.                                 parsing=params; /* continue the loop */
  1070.                             }
  1071.                     }
  1072.                     break;
  1073.  
  1074.                 case params:
  1075.                 {
  1076.                     char *bptmp; /* needed for fD_NewParam */
  1077.  
  1078.                     /* look for parameters now */
  1079.  
  1080.                     for (bnext = bpoint; *bnext && *bnext!=',' && *bnext!=')';
  1081.                     bnext++);
  1082.  
  1083.                     if (*bnext)
  1084.                     {
  1085.                         bptmp=bpoint;
  1086.  
  1087.                         if (*bnext == ')')
  1088.                         {
  1089.                             if (bnext[1] != '(')
  1090.                             {
  1091.                                 fprintf(stderr, "registers expected in line %lu: %s\n",
  1092.                                     infile->lineno, infile->line);
  1093.                                 fF_SetError(infile, nodef);
  1094.                             }
  1095.                             else
  1096.                             {
  1097.                                 parsing=regs;
  1098.                                 bpoint=bnext+2;
  1099.                             }
  1100.                         }
  1101.                         else
  1102.                             bpoint = bnext+1;
  1103.  
  1104.                         /* terminate string and advance to next item */
  1105.  
  1106.                         *bnext='\0';
  1107.                         fD_NewParam(obj, fD_ParamNum(obj), bptmp);
  1108.                     }
  1109.                     else
  1110.                     {
  1111.                         fF_SetError(infile, nodef);
  1112.                         fprintf(stderr, "param expected in line %lu: %s\n",
  1113.                             infile->lineno, infile->line);
  1114.                     }
  1115.                     break;  /* switch parsing */
  1116.                 }
  1117.  
  1118.                 case regs:
  1119.                     /* look for parameters now */
  1120.  
  1121.                     for (bnext=bpoint; *bnext && *bnext!='/' && *bnext!=',' &&
  1122.                     *bnext!=')'; bnext++);
  1123.  
  1124.                     if (*bnext)
  1125.                     {
  1126.                         if (')'==*bnext)
  1127.                         {
  1128.                             /* wow, we've finished */
  1129.                             fF_SetOffset(infile, fF_GetOffset(infile)-6);
  1130.                             parsing=ready;
  1131.                         }
  1132.                         *bnext = '\0';
  1133.  
  1134.                         bpoint[0]=tolower(bpoint[0]);
  1135.  
  1136.                         if ((bpoint[0]=='d' || bpoint[0]=='a') && bpoint[1]>='0' &&
  1137.                         bpoint[1]<='8' && bnext==bpoint+2)
  1138.                             fD_NewReg(obj, fD_RegNum(obj),
  1139.                                 bpoint[1]-'0'+(bpoint[0]=='a'? 8 : 0));
  1140.                         else
  1141.                             if (bnext!=bpoint)
  1142.                             {
  1143.                                 /* it is when our function is void */
  1144.                                 fprintf(stderr, "illegal register %s in line %ld\n",
  1145.                                     bpoint, infile->lineno);
  1146.                                 fF_SetError(infile, nodef);
  1147.                             }
  1148.                         bpoint = bnext+1;
  1149.                     }
  1150.                     else
  1151.                     {
  1152.                         fF_SetError(infile, nodef);
  1153.                         fprintf(stderr, "reg expected in line %lu\n",
  1154.                             infile->lineno);
  1155.                     }
  1156.                     break; /* switch parsing */
  1157.  
  1158.                 case ready:
  1159.                     fprintf(stderr, "internal error, use another compiler.\n");
  1160.                     break;
  1161.             }
  1162.         }
  1163.  
  1164.         free(buf);
  1165.         return fF_GetError(infile);
  1166.     }
  1167.     else
  1168.     {
  1169.         illparams("fD_parsefd");
  1170.         return real_error;
  1171.     }
  1172. }
  1173.  
  1174. Error
  1175. fD_parsepr(fdDef* obj, fdFile* infile)
  1176. {
  1177.     char    *buf;        /* a copy of infile->line                            */
  1178.     char    *bpoint,    /* cursor in buf                                        */
  1179.             *bnext,    /* looking for the end                                */
  1180.             *lowarg;    /* beginning of this argument                        */
  1181.     long    obraces;    /* count of open braces                                */
  1182.     regs    count,    /* count parameter number                            */
  1183.             args;        /* the number of arguments for this function */
  1184.  
  1185.     if (!(obj && infile && fF_GetError(infile)==false))
  1186.     {
  1187.         illparams("fD_parsepr");
  1188.         fF_SetError(infile, real_error);
  1189.         return real_error;
  1190.     }
  1191.     if (!NewString(&buf, infile->line))
  1192.     {
  1193.         fprintf(stderr, "no mem for fD_parsepr\n");
  1194.         fF_SetError(infile, real_error);
  1195.         return real_error;
  1196.     }
  1197.     fF_SetError(infile, false);
  1198.  
  1199.     bpoint=strchr(buf, '(');
  1200.     while (--bpoint>=buf && strstr(bpoint, fD_GetName(obj))!=bpoint);
  1201.     if (bpoint>=buf)
  1202.     {
  1203.         while (--bpoint >= buf && (*bpoint==' ' || *bpoint=='\t'));
  1204.         *++bpoint='\0';
  1205.  
  1206.         fD_NewType(obj, buf);
  1207.  
  1208.         while (bpoint && *bpoint++!='('); /* one beyond '(' */
  1209.  
  1210.         lowarg=bpoint;
  1211.         obraces=0;
  1212.  
  1213.         for (count=0, args=fD_RegNum(obj); count<args; bpoint=bnext+1)
  1214.         {
  1215.             while (*bpoint && (*bpoint==' ' || *bpoint=='\t')) /* ignore spaces */
  1216.                 bpoint++;
  1217.  
  1218.             bnext=strpbrk(bpoint, "(),");
  1219.  
  1220.             if (bnext)
  1221.             {
  1222.                 switch (*bnext)
  1223.                 {
  1224.                     case '(':
  1225.                         if (!obraces)
  1226.                         {
  1227.                             if (fD_GetFuncParNum(obj)!=illegal &&
  1228.                             fD_GetFuncParNum(obj)!=count)
  1229.                                 fprintf(stderr, "Warning: two parameters of type "
  1230.                                     "pointer to function are used.\nThis is not "
  1231.                                     "supported!\n");
  1232.                             fD_SetFuncParNum(obj, count);
  1233.                         }
  1234.                         obraces++;
  1235.                         DBP(fprintf(stderr, "< (%ld%s >", obraces, bnext));
  1236.                         break;
  1237.  
  1238.                     case ')':
  1239.                         if (obraces)
  1240.                         {
  1241.                             DBP(fprintf(stderr, "< )%ld%s >", obraces, bnext));
  1242.                             obraces--;
  1243.                         }
  1244.                         else
  1245.                         {
  1246.                             *bnext='\0';
  1247.                             DBP(fprintf(stderr, "< )0> [LAST PROTO=%s]", lowarg));
  1248.                             fD_NewProto(obj, count, lowarg);
  1249.                             lowarg=bnext+1;
  1250.  
  1251.                             if (count!=args-1)
  1252.                             {
  1253.                                 DBP(fprintf(stderr, "%s needs %u arguments and got %u.\n",
  1254.                                     fD_GetName(obj), args, count+1));
  1255.                                 fF_SetError(infile, nodef);
  1256.                             }
  1257.                             count++;
  1258.                         }
  1259.                         break;
  1260.  
  1261.                     case ',':
  1262.                         if (!obraces)
  1263.                         {
  1264.                             *bnext='\0';
  1265.                             DBP(fprintf(stderr, " [PROTO=%s] ", lowarg));
  1266.                             fD_NewProto(obj, count, lowarg);
  1267.                             lowarg=bnext+1;
  1268.                             count++;
  1269.                         }
  1270.                         break;
  1271.  
  1272.                     default:
  1273.                         fprintf(stderr, "faulty strpbrk in line %lu.\n",
  1274.                             infile->lineno);
  1275.                 }
  1276.             }
  1277.             else
  1278.             {
  1279.                 DBP(fprintf(stderr, "faulty argument %u in line %lu.\n", count+1,
  1280.                     infile->lineno));
  1281.                 count=args; /* this will effectively quit the for loop */
  1282.                 fF_SetError(infile, nodef);
  1283.             }
  1284.         }
  1285.         if (fD_ProtoNum(obj)!=fD_RegNum(obj))
  1286.             fF_SetError(infile, nodef);
  1287.     }
  1288.     else
  1289.     {
  1290.         fprintf(stderr, "fD_parsepr was fooled in line %lu\n", infile->lineno);
  1291.         fprintf(stderr, "function , definition %s.\n",
  1292.             /* fD_GetName(obj),*/ infile->line);
  1293.         fF_SetError(infile, nodef);
  1294.     }
  1295.  
  1296.     free(buf);
  1297.     return fF_GetError(infile);
  1298. }
  1299.  
  1300. int
  1301. fD_cmpName(const void* big, const void* small) /* for qsort and bsearch */
  1302. {
  1303.     return strcmp(fD_GetName(*(fdDef**)big), fD_GetName(*(fdDef**)small));
  1304. }
  1305.  
  1306. const static char *TagExcTable[]=
  1307. {
  1308.     "BuildEasyRequestArgs",    "BuildEasyRequest",
  1309.     "DoDTMethodA",                "DoDTMethod",
  1310.     "DoGadgetMethodA",        "DoGadgetMethod",
  1311.     "EasyRequestArgs",        "EasyRequest",
  1312.     "MUI_MakeObjectA",        "MUI_MakeObject",
  1313.     "MUI_RequestA",            "MUI_Request",
  1314.     "PrintDTObjectA",            "PrintDTObject",
  1315.     "UMSVLog",                    "UMSLog",
  1316.     "VFWritef",                    "FWritef",
  1317.     "VFPrintf",                    "FPrintf",
  1318.     "VPrintf",                    "Printf",
  1319. };
  1320.  
  1321. const char*
  1322. taggedfunction(const fdDef* obj)
  1323. {
  1324.     shortcard numregs=fD_RegNum(obj);
  1325.     unsigned int count;
  1326.     const char *name=fD_GetName(obj);
  1327.     static char newname[200];    /* Hope will be enough... static because used
  1328.                                             out of the function. */
  1329.     const char *lastarg;
  1330.     const static char *TagExcTable2[]=
  1331.     {
  1332.         "ApplyTagChanges",
  1333.         "CloneTagItems",
  1334.         "FindTagItem",
  1335.         "FreeTagItems",
  1336.         "GetTagData",
  1337.         "PackBoolTags",
  1338.         "PackStructureTags",
  1339.         "RefreshTagItemClones",
  1340.         "UnpackStructureTags",
  1341.     };
  1342.  
  1343.     if (!numregs)
  1344.         return NULL;
  1345.  
  1346.     for (count=0; count<sizeof TagExcTable/sizeof TagExcTable[0]; count+=2)
  1347.         if (strcmp(name, TagExcTable[count])==0)
  1348.             return TagExcTable[count+1];
  1349.  
  1350.     for (count=0; count<sizeof TagExcTable2/sizeof TagExcTable2[0]; count++)
  1351.         if (strcmp(name, TagExcTable2[count])==0)
  1352.             return NULL;
  1353.  
  1354.     lastarg=fD_GetProto(obj, numregs-1);
  1355.     if (strncmp(lastarg, "struct", 6))
  1356.         return NULL;
  1357.     lastarg+=6;
  1358.     while (*lastarg==' ' || *lastarg=='\t')
  1359.         lastarg++;
  1360.     if (strncmp(lastarg, "TagItem", 7))
  1361.         return NULL;
  1362.     lastarg+=7;
  1363.     while (*lastarg==' ' || *lastarg=='\t')
  1364.         lastarg++;
  1365.     if (strcmp(lastarg, "*"))
  1366.         return NULL;
  1367.  
  1368.     strcpy(newname, name);
  1369.     if (newname[strlen(newname)-1]=='A')
  1370.         newname[strlen(newname)-1]='\0';
  1371.     else
  1372.         if (strlen(newname)>7 && !strcmp(newname+strlen(newname)-7, "TagList"))
  1373.             strcpy(newname+strlen(newname)-4, "s");
  1374.         else
  1375.             strcat(newname, "Tags");
  1376.     return newname;
  1377. }
  1378.  
  1379. const char*
  1380. aliasfunction(const char* name)
  1381. {
  1382.     const static char *AliasTable[]=
  1383.     {
  1384.         "AllocDosObject",    "AllocDosObjectTagList",
  1385.         "CreateNewProc",    "CreateNewProcTagList",
  1386.         "NewLoadSeg",        "NewLoadSegTagList",
  1387.         "System",            "SystemTagList",
  1388.     };
  1389.     unsigned int count;
  1390.     for (count=0; count<sizeof AliasTable/sizeof AliasTable[0]; count++)
  1391.         if (strcmp(name, AliasTable[count])==0)
  1392.             return AliasTable[count+(count%2 ? -1 : 1)];
  1393.     return NULL;
  1394. }
  1395.  
  1396. void
  1397. fD_write(FILE* outfile, const fdDef* obj)
  1398. {
  1399.     shortcard count, numregs;
  1400.     const char *chtmp, *tagname, *name, *rettype;
  1401.     int vd=0, a45=0, d7=0;
  1402.  
  1403.     DBP(fprintf(stderr, "func %s\n", fD_GetName(obj)));
  1404.  
  1405.     numregs=fD_RegNum(obj);
  1406.  
  1407.     if ((rettype=fD_GetType(obj))==fD_nostring)
  1408.     {
  1409.         fprintf(stderr, "%s has no prototype.\n", fD_GetName(obj));
  1410.         return;
  1411.     }
  1412.     if (!stricmp(rettype, "void"))
  1413.         vd = 1; /* set flag */
  1414.     for (count=d0; count<numregs; count++)
  1415.     {
  1416.         const char *reg=fD_GetRegStr(obj, count);
  1417.         if (strcmp(reg, "a4")==0 || strcmp(reg, "a5")==0)
  1418.             if (!a45)
  1419.                 a45=(strcmp(reg, "a4") ? 5 : 4); /* set flag */
  1420.             else /* Security check */
  1421.                 fprintf(stderr, "Warning: both a4 and a5 are used. This is not "
  1422.                     "supported!\n");
  1423.         if (strcmp(reg, "d7")==0) /* Used only when a45!=0 */
  1424.             d7=1;
  1425.     }
  1426.     if (a45 && d7) /* Security check */
  1427.         fprintf(stderr, "Warning: d7 and a4 or a5 are used. This is not "
  1428.             "supported!\n");
  1429.  
  1430.     name=fD_GetName(obj);
  1431.  
  1432.     if (fD_ProtoNum(obj)!=numregs)
  1433.     {
  1434.         fprintf(stderr, "%s gets %d fd args and %d proto%s.\n", name, numregs,
  1435.             fD_ProtoNum(obj), fD_ProtoNum(obj)!= 1 ? "s" : "");
  1436.         return;
  1437.     }
  1438.  
  1439.     if (output_mode==NEW)
  1440.     {
  1441.         fprintf(outfile, "#define %s(", name);
  1442.  
  1443.         if (numregs>0)
  1444.         {
  1445.             for (count=d0; count<numregs-1; count++)
  1446.                 fprintf(outfile, "%s, ", fD_GetParam(obj, count));
  1447.             fprintf(outfile, "%s", fD_GetParam(obj, count));
  1448.         }
  1449.  
  1450.         fprintf(outfile, ") \\\n\tLP%d%s%s%s%s(0x%lx, ", numregs,
  1451.             (vd ? "NR" : ""), (a45 ? (a45==4 ? "A4" : "A5") : ""),
  1452.             (BaseName[0] ? "" : "UB"),
  1453.             (fD_GetFuncParNum(obj)==illegal ? "" : "FP"), -fD_GetOffset(obj));
  1454.         if (!vd)
  1455.             fprintf(outfile, "%s, ", rettype);
  1456.         fprintf(outfile, "%s, ", name);
  1457.  
  1458.         for (count=d0; count<numregs; count++)
  1459.         {
  1460.             chtmp=fD_GetRegStr(obj, count);
  1461.             if (a45 && (strcmp(chtmp, "a4")==0 || strcmp(chtmp, "a5")==0))
  1462.                 chtmp="d7";
  1463.             fprintf(outfile, "%s, %s, %s%s", (fD_GetFuncParNum(obj)==count ?
  1464.                 "__fpt" : fD_GetProto(obj, count)), fD_GetParam(obj, count),
  1465.                 chtmp, (count==numregs-1 && !BaseName[0] ? "" : ", "));
  1466.         }
  1467.  
  1468.         if (BaseName[0]) /* was "##base" used? */
  1469.             fprintf(outfile, "\\\n\t, %s_BASE_NAME", BaseNamU);
  1470.         if (fD_GetFuncParNum(obj)!=illegal)
  1471.         {
  1472.             fprintf(outfile, ", ");
  1473.             fprintf(outfile, fD_GetProto(obj, fD_GetFuncParNum(obj)), "__fpt");
  1474.         }
  1475.         fprintf(outfile, ")\n\n");
  1476.     }
  1477.     else
  1478.     {
  1479.         fprintf(outfile, "%s__inline %s\n%s(%s",
  1480.             (output_mode==STUBS ? "" : "extern "), rettype, name,
  1481.             (BaseName[0] ? (numregs ? "BASE_PAR_DECL " : "BASE_PAR_DECL0") : ""));
  1482.  
  1483.         for (count=d0; count<numregs; count++)
  1484.         {
  1485.             chtmp=fD_GetProto(obj, count);
  1486.             if (fD_GetFuncParNum(obj)==count)
  1487.                 fprintf(outfile, chtmp, fD_GetParam(obj, count));
  1488.             else
  1489.                 fprintf(outfile, "%s%s%s", chtmp, (*(chtmp+strlen(chtmp)-1)=='*' ?
  1490.                     "" : " "), fD_GetParam(obj, count));
  1491.             if (count<numregs-1)
  1492.                 fprintf(outfile, ", ");
  1493.         }
  1494.  
  1495.         fprintf(outfile, ")\n{\n%s", (BaseName[0] ? "   BASE_EXT_DECL\n" : ""));
  1496.         if (!vd)
  1497.             fprintf(outfile, "   register %s%sres __asm(\"d0\");\n", rettype,
  1498.                 (*(rettype+strlen(rettype)-1)=='*' ? "" : " "));
  1499.  
  1500.         if (BaseName[0])
  1501.             fprintf(outfile, "   register struct %s *a6 __asm(\"a6\") = BASE_NAME;\n",
  1502.                 StdLib);
  1503.  
  1504.         for (count=d0; count<numregs; count++)
  1505.         {
  1506.             chtmp=fD_GetRegStr(obj, count);
  1507.             if (a45 && (strcmp(chtmp, "a4")==0 || strcmp(chtmp, "a5")==0))
  1508.                 chtmp="d7";
  1509.             if (fD_GetFuncParNum(obj)==count)
  1510.             {
  1511.                 fprintf(outfile, "   register ");
  1512.                 fprintf(outfile, fD_GetProto(obj, count), chtmp);
  1513.                 fprintf(outfile, " __asm(\"%s\") = %s;\n", chtmp, fD_GetParam(obj,
  1514.                     count));
  1515.             }
  1516.             else
  1517.             {
  1518.                 const char *proto=fD_GetProto(obj, count);
  1519.                 fprintf(outfile, "   register %s%s%s __asm(\"%s\") = %s;\n",
  1520.                     proto, (*(proto+strlen(proto)-1)=='*' ? "" : " "), chtmp,
  1521.                     chtmp, fD_GetParam(obj, count));
  1522.             }
  1523.         }
  1524.         if (a45)
  1525.             fprintf(outfile, "   __asm volatile (\"exg d7,%s\\n\\t"
  1526.                 "jsr a6@(-0x%lx:W)\\n\\texg d7,%s\"\n", (a45==4 ? "a4" : "a5"),
  1527.                 -fD_GetOffset(obj), (a45==4 ? "a4" : "a5"));
  1528.         else
  1529.             fprintf(outfile, "   __asm volatile (\"jsr a6@(-0x%lx:W)\"\n",
  1530.                 -fD_GetOffset(obj));
  1531.  
  1532.         fprintf(outfile, (vd ? "   : /* No Output */\n" : "   : \"=r\" (res)\n"));
  1533.  
  1534.         fprintf(outfile, "   : ");
  1535.         if (BaseName[0])
  1536.             fprintf(outfile, "\"r\" (a6)%s", (numregs ? ", ": ""));
  1537.  
  1538.         for (count=d0; count<numregs; count++)
  1539.         {
  1540.             chtmp=fD_GetRegStr(obj, count);
  1541.             if (a45 && (strcmp(chtmp, "a4")==0 || strcmp(chtmp, "a5")==0))
  1542.                 chtmp="d7";
  1543.             fprintf(outfile, "\"r\" (%s)%s", chtmp, (count<numregs-1 ? ", " : ""));
  1544.         }
  1545.         fprintf(outfile, "\n   : \"d0\", \"d1\", \"a0\", \"a1\", \"fp0\", \"fp1\"");
  1546.  
  1547.         if (vd)
  1548.             fprintf(outfile, ", \"cc\", \"memory\");\n}\n\n"); /* { */
  1549.         else
  1550.             fprintf(outfile, ", \"cc\", \"memory\");\n   return res;\n}\n\n");
  1551.     }
  1552.  
  1553.     if ((tagname=aliasfunction(fD_GetName(obj)))!=0)
  1554.     {
  1555.         fprintf(outfile, "#define %s(", tagname);
  1556.         for (count=d0; count<numregs-1; count++)
  1557.             fprintf(outfile, "a%d, ", count);
  1558.         fprintf(outfile, "a%d) %s (", count, name);
  1559.         for (count=d0; count<numregs-1; count++)
  1560.             fprintf(outfile, "(a%d), ", count);
  1561.         fprintf(outfile, "(a%d))\n\n", count);
  1562.     }
  1563.  
  1564.     if ((tagname=taggedfunction(obj))!=0)
  1565.     {
  1566.         if (output_mode!=STUBS)
  1567.         {
  1568.             fprintf(outfile, "#ifndef NO_INLINE_STDARG\n#define %s(", tagname);
  1569.  
  1570.             for (count=d0; count<numregs-1; count++)
  1571.                 fprintf(outfile, "a%d, ", count);
  1572.  
  1573.             fprintf(outfile, "tags...) \\\n\t({ULONG _tags[] = { tags }; %s(",
  1574.                 name);
  1575.  
  1576.             for (count=d0; count<numregs-1; count++)
  1577.                 fprintf(outfile, "(a%d), ", count);
  1578.  
  1579.             fprintf(outfile, "(%s)_tags);})\n#endif /* !NO_INLINE_STDARG */\n\n",
  1580.                 fD_GetProto(obj, fD_RegNum(obj)-1));
  1581.         }
  1582.         else
  1583.         {
  1584.             fprintf(outfile, "%s %s(", rettype, tagname);
  1585.  
  1586.             for (count=d0; count<numregs-1; count++)
  1587.             {
  1588.                 chtmp=fD_GetProto(obj, count);
  1589.                 if (count==fD_GetFuncParNum(obj))
  1590.                     fprintf(outfile, chtmp, fD_GetParam(obj, count));
  1591.                 else
  1592.                     fprintf(outfile, "%s%s%s", chtmp,
  1593.                         (*(chtmp+strlen(chtmp)-1)=='*' ? "" : " "),
  1594.                         fD_GetParam(obj, count));
  1595.                 fprintf(outfile, ", ");
  1596.             }
  1597.  
  1598.             fprintf(outfile, "int tag, ...)\n{\n   ");
  1599.             if (!vd)
  1600.                 fprintf(outfile, "return ");
  1601.  
  1602.             fprintf(outfile, "%s(", name);
  1603.             for (count=d0; count<numregs-1; count++)
  1604.                 fprintf(outfile, "%s, ", fD_GetParam(obj, count));
  1605.  
  1606.             fprintf(outfile, "(%s)&tag);\n}\n\n", fD_GetProto(obj, fD_RegNum(obj)-1));
  1607.         }
  1608.     }
  1609.  
  1610.     if (strcmp(name, "DoPkt")==0)
  1611.     {
  1612.         fdDef *objnc=(fdDef*)obj;
  1613.         char newname[7]="DoPkt0";
  1614.         objnc->name=newname;
  1615.         for (count=2; count<7; count++)
  1616.         {
  1617.             regs reg=objnc->reg[count];
  1618.             char *proto=objnc->proto[count];
  1619.             objnc->reg[count]=illegal;
  1620.             objnc->proto[count]=fD_nostring;
  1621.             fD_write(outfile, objnc);
  1622.             objnc->reg[count]=reg;
  1623.             objnc->proto[count]=proto;
  1624.             newname[5]++;
  1625.         }
  1626.         objnc->name=(char*)name;
  1627.     }
  1628. }
  1629.  
  1630. int
  1631. varargsfunction(const char* proto, const char* funcname)
  1632. {
  1633.     const char *end=proto+strlen(proto)-1;
  1634.     while (isspace(*end))
  1635.         end--;
  1636.     if (*end--==';')
  1637.     {
  1638.         while (isspace(*end))
  1639.             end--;
  1640.         if (*end--==')')
  1641.         {
  1642.             while (isspace(*end))
  1643.                 end--;
  1644.             if (!strncmp(end-2, "...", 3))
  1645.             {
  1646.                 /* Seems to be a varargs function. Check if it will be recognized
  1647.                     as "tagged". */
  1648.                 unsigned int count;
  1649.                 char fixedname[200]; /* Hope will be enough... */
  1650.                 fdDef *tmpdef;
  1651.  
  1652.                 for (count=0; count<sizeof TagExcTable/sizeof TagExcTable[0];
  1653.                 count+=2)
  1654.                     if (strcmp(funcname, TagExcTable[count+1])==0)
  1655.                         return 1;
  1656.  
  1657.                 if (!(tmpdef=fD_ctor()))
  1658.                 {
  1659.                     fprintf(stderr, "No mem for FDs\n");
  1660.                     exit(EXIT_FAILURE);
  1661.                 }
  1662.  
  1663.                 strcpy(fixedname, funcname);
  1664.                 if (strlen(funcname)>4 &&
  1665.                 !strcmp(funcname+strlen(funcname)-4, "Tags"))
  1666.                 {
  1667.                     /* Might be either nothing or "TagList". */
  1668.                     fixedname[strlen(fixedname)-4]='\0';
  1669.                     fD_NewName(tmpdef, fixedname);
  1670.                     if (bsearch(&tmpdef, arrdefs, fds, sizeof arrdefs[0],
  1671.                     fD_cmpName))
  1672.                         return 1;
  1673.  
  1674.                     strcat(fixedname, "TagList");
  1675.                     fD_NewName(tmpdef, fixedname);
  1676.                     if (bsearch(&tmpdef, arrdefs, fds, sizeof arrdefs[0],
  1677.                     fD_cmpName))
  1678.                         return 1;
  1679.                 }
  1680.                 else
  1681.                 {
  1682.                     strcat(fixedname, "A");
  1683.                     fD_NewName(tmpdef, fixedname);
  1684.                     if (bsearch(&tmpdef, arrdefs, fds, sizeof arrdefs[0],
  1685.                     fD_cmpName))
  1686.                         return 1;
  1687.                 }
  1688.             }
  1689.         }
  1690.     }
  1691.     return 0;
  1692. }
  1693.  
  1694. int
  1695. ishandleddifferently(const char* proto, const char* funcname)
  1696. {
  1697.     /* First check if this is a vararg call? */
  1698.     if (varargsfunction(proto, funcname))
  1699.         return 1;
  1700.  
  1701.     /* It might be a dos.library "alias" name. */
  1702.     if (aliasfunction(funcname))
  1703.         return 1;
  1704.  
  1705.     /* It might be one from dos.library/DoPkt() family. */
  1706.     if (strlen(funcname)==6 && !strncmp(funcname, "DoPkt", 5) &&
  1707.     funcname[5]>='0' && funcname[6]<='4')
  1708.         return 1;
  1709.  
  1710.     /* Finally, it can be intuition.library/ReportMouse1(). */
  1711.     return !strcmp(funcname, "ReportMouse1");
  1712. }
  1713.  
  1714. void
  1715. printusage(const char* exename)
  1716. {
  1717.     fprintf(stderr,
  1718.         "Usage: %s [options] fd-file clib-file [[-o] output-file]\n"
  1719.         "Options:\n"
  1720.         "--new\t\tpreprocessor based (default)\n"
  1721.         "--old\t\tinline based\n"
  1722.         "--stubs\t\tlibrary stubs\n"
  1723.         "--proto\t\tbuild proto files (no clib-file required)\n"
  1724.         "--version\tprint version number and exit\n", exename);
  1725. }
  1726.  
  1727. void output_proto(FILE* outfile)
  1728. {
  1729.     fprintf(outfile,
  1730.         "/* Automatically generated header! Do not edit! */\n\n"
  1731.         "#ifndef PROTO_%s_H\n"
  1732.         "#define PROTO_%s_H\n\n"
  1733.         "#include <clib/%s_protos.h>\n\n"
  1734.         "#ifdef __GNUC__\n"
  1735.         "#include <inline/%s.h>\n"
  1736.         "#endif /* __GNUC__ */\n\n",
  1737.         BaseNamU, BaseNamU, BaseNamL, BaseNamL);
  1738.  
  1739.     if (BaseName[0])
  1740.         fprintf(outfile,
  1741.             "#ifndef __NOLIBBASE__\n"
  1742.             "extern struct %s *\n"
  1743.             "#ifdef __CONSTLIBBASEDECL__\n"
  1744.             "__CONSTLIBBASEDECL__\n"
  1745.             "#endif /* __CONSTLIBBASEDECL__ */\n"
  1746.             "%s;\n"
  1747.             "#endif /* !__NOLIBBASE__ */\n\n",
  1748.             StdLib, BaseName);
  1749.  
  1750.     fprintf(outfile,
  1751.         "#endif /* !PROTO_%s_H */\n", BaseNamU);
  1752. }
  1753.  
  1754. /******************************************************************************/
  1755.  
  1756. int
  1757. main(int argc, char** argv)
  1758. {
  1759.     fdDef *tmpdef,            /* a dummy to contain the name to look for */
  1760.             *founddef;        /* the fdDef for which we found a prototype */
  1761.     fdFile *myfile;
  1762.     char *tmpstr;
  1763.     FILE *outfile;
  1764.     char *fdfilename=0, *clibfilename=0, *outfilename=0;
  1765.  
  1766.     int count;
  1767.     Error lerror;
  1768.  
  1769.     for (count=1; count<argc; count++)
  1770.     {
  1771.         char *option=argv[count];
  1772.         if (*option=='-')
  1773.         {
  1774.             option++;
  1775.             if (strcmp(option, "o")==0)
  1776.             {
  1777.                 if (count==argc-1 || outfilename)
  1778.                 {
  1779.                     printusage(argv[0]);
  1780.                     return EXIT_FAILURE;
  1781.                 }
  1782.                 if (strcmp(argv[++count], "-"))
  1783.                     outfilename=argv[count];
  1784.             }
  1785.             else
  1786.             {
  1787.                 if (*option=='-') /* Accept GNU-style '--' options */
  1788.                     option++;
  1789.                 if (strcmp(option, "new")==0)
  1790.                     output_mode=NEW;
  1791.                 else if (strcmp(option, "old")==0)
  1792.                     output_mode=OLD;
  1793.                 else if (strcmp(option, "stubs")==0)
  1794.                     output_mode=STUBS;
  1795.                 else if (strcmp(option, "proto")==0)
  1796.                     output_mode=PROTO;
  1797.                 else if (strcmp(option, "version")==0)
  1798.                 {
  1799.                     fprintf(stderr, "fd2inline version " VERSION "\n");
  1800.                     return EXIT_SUCCESS;
  1801.                 }
  1802.                 else
  1803.                 {
  1804.                     printusage(argv[0]);
  1805.                     return EXIT_FAILURE;
  1806.                 }
  1807.             }
  1808.         }
  1809.         else
  1810.         {
  1811.             /* One of the filenames */
  1812.             if (!fdfilename)
  1813.                 fdfilename=option;
  1814.             else if (!clibfilename)
  1815.                 clibfilename=option;
  1816.             else if (!outfilename)
  1817.                 outfilename=option;
  1818.             else
  1819.             {
  1820.                 printusage(argv[0]);
  1821.                 return EXIT_FAILURE;
  1822.             }
  1823.         }
  1824.     }
  1825.  
  1826.     if (!fdfilename || (!clibfilename && output_mode!=PROTO))
  1827.     {
  1828.         printusage(argv[0]);
  1829.         return EXIT_FAILURE;
  1830.     }
  1831.  
  1832.     if (!(arrdefs=malloc(FDS*sizeof(fdDef*))))
  1833.     {
  1834.         fprintf(stderr, "No mem for FDs\n");
  1835.         return EXIT_FAILURE;
  1836.     }
  1837.     for (count=0; count<FDS; count++)
  1838.         arrdefs[count]=NULL;
  1839.  
  1840.     if (!(myfile=fF_ctor(fdfilename)))
  1841.     {
  1842.         fprintf(stderr, "Couldn't open file '%s'.\n", fdfilename);
  1843.         return EXIT_FAILURE;
  1844.     }
  1845.  
  1846.     lerror=false;
  1847.  
  1848.     for (count=0; count<FDS && lerror==false; count++)
  1849.     {
  1850.         if (!(arrdefs[count]=fD_ctor()))
  1851.         {
  1852.             fprintf(stderr, "No mem for FDs\n" );
  1853.             return EXIT_FAILURE;
  1854.         }
  1855.         do
  1856.         {
  1857.             if ((lerror=fF_readln(myfile))==false)
  1858.             {
  1859.                 fF_SetError(myfile, false);
  1860.                 lerror=fD_parsefd(arrdefs[count], myfile);
  1861.             }
  1862.         }
  1863.         while (lerror==nodef);
  1864.     }
  1865.     if (count<FDS)
  1866.     {
  1867.         count--;
  1868.         fD_dtor(arrdefs[count]);
  1869.         arrdefs[count]=NULL;
  1870.     }
  1871.     fds=count;
  1872.  
  1873.     qsort(arrdefs, count, sizeof arrdefs[0], fD_cmpName);
  1874.  
  1875.     if (output_mode!=NEW)
  1876.     {
  1877.         unsigned int count2;
  1878.         StdLib="Library";
  1879.  
  1880.         for (count2=0; count2<sizeof LibExcTable/sizeof LibExcTable[0]; count2+=2)
  1881.             if (strcmp(BaseName, LibExcTable[count2])==0)
  1882.             {
  1883.                 StdLib=LibExcTable[count2+1];
  1884.                 break;
  1885.             }
  1886.     }
  1887.  
  1888.     fF_dtor(myfile);
  1889.  
  1890.     if (output_mode!=PROTO)
  1891.     {
  1892.         if (!(myfile=fF_ctor(clibfilename)))
  1893.         {
  1894.             fprintf(stderr, "Couldn't open file '%s'.\n", clibfilename);
  1895.             return EXIT_FAILURE;
  1896.         }
  1897.  
  1898.         if (!(tmpdef=fD_ctor()))
  1899.         {
  1900.             fprintf(stderr, "No mem for FDs\n");
  1901.             return EXIT_FAILURE;
  1902.         }
  1903.  
  1904.         for (lerror=false; lerror==false || lerror==nodef;)
  1905.             if ((lerror=fF_readln(myfile))==false)
  1906.             {
  1907.                 fF_SetError(myfile, false); /* continue even on errors */
  1908.                 tmpstr=fF_FuncName(myfile);
  1909.  
  1910.                 if (tmpstr)
  1911.                 {
  1912.                    fdDef **res;
  1913.                     fD_NewName(tmpdef, tmpstr);
  1914.                     res=(fdDef**)bsearch(&tmpdef, arrdefs, fds, sizeof arrdefs[0],
  1915.                         fD_cmpName);
  1916.  
  1917.                     if (res)
  1918.                     {
  1919.                         founddef=*res;
  1920.                         DBP(fprintf(stderr, "found (%s).\n", fD_GetName(founddef)));
  1921.                         fF_SetError(myfile, false);
  1922.                         lerror=fD_parsepr(founddef, myfile);
  1923.                     }
  1924.                     else
  1925.                         if (!ishandleddifferently(myfile->line, tmpstr))
  1926.                             fprintf(stderr, "don't know what to do with <%s> in line %lu.\n",
  1927.                                 tmpstr, myfile->lineno);
  1928.                     free(tmpstr);
  1929.                 }
  1930.             }
  1931.  
  1932.         fD_dtor(tmpdef);
  1933.  
  1934.         fF_dtor(myfile);
  1935.     }
  1936.  
  1937.     if (strlen(fdfilename)>7 &&
  1938.     !strcmp(fdfilename+strlen(fdfilename)-7, "_lib.fd"))
  1939.     {
  1940.         char *str=fdfilename+strlen(fdfilename)-8;
  1941.         while (str!=fdfilename && str[-1]!='/' && str[-1]!=':')
  1942.             str--;
  1943.         strncpy(BaseNamL, str, strlen(str)-7);
  1944.         strncpy(BaseNamU, str, strlen(str)-7);
  1945.         BaseNamU[strlen(str)-7]='\0';
  1946.     }
  1947.     else
  1948.     {
  1949.         /* Shouldn't really happen, but... */
  1950.         strcpy(BaseNamU, BaseName);
  1951.         if (strlen(BaseNamU)>4 && strcmp(BaseNamU+strlen(BaseNamU)-4, "Base")==0)
  1952.             BaseNamU[strlen(BaseNamU)-4]='\0';
  1953.     }
  1954.     StrUpr(BaseNamU);
  1955.  
  1956.     if (outfilename)
  1957.     {
  1958.         if (!(outfile=fopen(outfilename, "w")))
  1959.         {
  1960.             fprintf(stderr, "Couldn't open output file.\n");
  1961.             return EXIT_FAILURE;
  1962.         }
  1963.     }
  1964.     else
  1965.         outfile=stdout;
  1966.  
  1967.     if (output_mode==PROTO)
  1968.         output_proto(outfile);
  1969.     else
  1970.     {
  1971.         fprintf(outfile,
  1972.             "/* Automatically generated header! Do not edit! */\n\n"
  1973.             "#ifndef _INLINE_%s_H\n"
  1974.             "#define _INLINE_%s_H\n\n"
  1975.             "%s\n\n", BaseNamU, BaseNamU, (output_mode==NEW ?
  1976.                 "#ifndef __INLINE_MACROS_H\n"
  1977.                 "#include <inline/macros.h>\n"
  1978.                 "#endif /* !__INLINE_MACROS_H */" :
  1979.                 "#ifndef __INLINE_STUB_H\n"
  1980.                 "#include <inline/stubs.h>\n"
  1981.                 "#endif /* !__INLINE_STUB_H */"));
  1982.         if (BaseName[0])
  1983.         {
  1984.             if (output_mode==NEW)
  1985.                 fprintf(outfile,
  1986.                     "#ifndef %s_BASE_NAME\n"
  1987.                     "#define %s_BASE_NAME %s\n"
  1988.                     "#endif /* !%s_BASE_NAME */\n\n",
  1989.                     BaseNamU, BaseNamU, BaseName, BaseNamU);
  1990.             else
  1991.                 fprintf(outfile,
  1992.                     "#ifndef BASE_EXT_DECL\n"
  1993.                     "#define BASE_EXT_DECL\n"
  1994.                     "#define BASE_EXT_DECL0 extern struct %s *%s;\n"
  1995.                     "#endif /* !BASE_EXT_DECL */\n"
  1996.                     "#ifndef BASE_PAR_DECL\n"
  1997.                     "#define BASE_PAR_DECL\n"
  1998.                     "#define BASE_PAR_DECL0 void\n"
  1999.                     "#endif /* !BASE_PAR_DECL */\n"
  2000.                     "#ifndef BASE_NAME\n"
  2001.                     "#define BASE_NAME %s\n"
  2002.                     "#endif /* !BASE_NAME */\n\n"
  2003.                     "BASE_EXT_DECL0\n\n", StdLib, BaseName, BaseName);
  2004.         }
  2005.  
  2006.         for (count=0; count<FDS && arrdefs[count]; count++)
  2007.         {
  2008.             DBP(fprintf(stderr, "outputting %ld...\n", count));
  2009.  
  2010.             fD_write(outfile, arrdefs[count]);
  2011.             fD_dtor(arrdefs[count]);
  2012.             arrdefs[count]=NULL;
  2013.         }
  2014.  
  2015.         if (output_mode==OLD || output_mode==STUBS)
  2016.             if (BaseName[0])
  2017.                 fprintf(outfile,
  2018.                     "#undef BASE_EXT_DECL\n"
  2019.                     "#undef BASE_EXT_DECL0\n"
  2020.                     "#undef BASE_PAR_DECL\n"
  2021.                     "#undef BASE_PAR_DECL0\n"
  2022.                     "#undef BASE_NAME\n\n");
  2023.         fprintf(outfile, "#endif /* !_INLINE_%s_H */\n", BaseNamU);
  2024.     }
  2025.  
  2026.     free(arrdefs);
  2027.  
  2028.     return EXIT_SUCCESS;
  2029. }
  2030.